
#include <BFont>
#include "member_BScrollArea.h"
#include "member_BScrollBar.h"

using namespace BWE;

member_BScrollArea::member_BScrollArea(BScrollArea* scrollArea)
{
	boss = scrollArea;
	areaAlign = Align_None;
	areaPolicy = Policy_Preferred;
	hScrollBar = 0;
	hScrollPolicy = ScrollPolicy_Auto;
	vScrollBar = 0;
	vScrollPolicy = ScrollPolicy_Auto;
	vstep = 10;
	hstep = 10;
	handleSize = 0;
	dirty = true;
}
member_BScrollArea::~member_BScrollArea()
{

}

bool member_BScrollArea::applyAreaPolicy()
{
	BRect temp = rawArea;
	BRect crect = boss->centerRect();
	if (areaAlign)
	{
		BRect rect = crect.align(areaAlign, temp.size());
		if (temp.width() <= crect.width())
			temp.setX(rect.x());
		if (temp.height() <= crect.height())
			temp.setY(rect.y());
	}
	else
	{
		int mx = 0;
		if (temp.width() <= crect.width())
		{
			if (temp.left() < crect.left())
				mx += crect.left() - temp.left();
			if (temp.right() > crect.right())
				mx += crect.right() - temp.right();
		}
		int my = 0;
		if (temp.height() <= crect.height())
		{
			if (temp.top() < crect.top())
				my += crect.top() - temp.top();
			if (temp.bottom() > crect.bottom())
				my += crect.bottom() - temp.bottom();
		}
		temp.move(mx, my);
	}
	if (temp.width() > crect.width())
	{
		if (temp.left() > crect.left())
			temp.move(crect.left() - temp.left(), 0);
		if (temp.right() < crect.right())
			temp.move(crect.right() - temp.right(), 0);
	}
	if (temp.height() > crect.height())
	{
		if (temp.top() > crect.top())
			temp.move(0, crect.top() - temp.top());
		if (temp.bottom() < crect.bottom())
			temp.move(0, crect.bottom() - temp.bottom());
	}
	if (areaPolicy.widthPolicy() > Policy_Fixed)
	{
		if (areaPolicy.widthPolicy() & Policy_Expanding && temp.width() < crect.width())
			temp.setWidth(crect.width());
		if (areaPolicy.widthPolicy() & Policy_Shrinking && temp.width() > crect.width())
			temp.setWidth(crect.width());
	}
	if (areaPolicy.heightPolicy() > Policy_Fixed)
	{
		if (areaPolicy.heightPolicy() & Policy_Expanding && temp.height() < crect.height())
			temp.setHeight(crect.height());
		if (areaPolicy.heightPolicy() & Policy_Shrinking && temp.height() > crect.height())
			temp.setHeight(crect.height());
	}
	if (area != temp)
	{
		area = temp;
		return true;
	}
	return false;
}
void member_BScrollArea::adjustScrollBar()
{
	const BRect& crect = boss->centerRect();

	if (hScrollBar)
	{
		if (hScrollPolicy <= ScrollPolicy_Never)
		{
			hScrollBar->setVisible(false);
		}
		else
		{
			int height = bMax(handleSize.height(), hScrollBar->preferSize(0, 0).height());
			if (hScrollPolicy == ScrollPolicy_Auto)
			{
				boss->setPerch(Part_Bottom, height);
				hScrollBar->setRect(boss->rect(Part_Bottom));
				hScrollBar->setVisible(crect.width() < area.width());
			}
			if (hScrollPolicy == ScrollPolicy_Always)
			{
				boss->setPerch(Part_Bottom, height);
				hScrollBar->setRect(boss->rect(Part_Bottom));
				hScrollBar->setVisible(true);
			}
			if(hScrollPolicy == ScrollPolicy_Floating)
			{
				BRect brect = boss->rect(Part_Bottom);
				hScrollBar->setRect(brect.x(), brect.bottom() - height, brect.width(), height);
			}
		}
		hScrollBar->setParent(boss);
		hScrollBar->setRange(0, area.width());
		hScrollBar->setPage(crect.width());
		hScrollBar->setValue(crect.left() - area.left());
		hScrollBar->raise();
	}
	if (vScrollBar)
	{
		if (vScrollPolicy <= ScrollPolicy_Never)
		{
			vScrollBar->setVisible(false);
		}
		else
		{
			int width = bMax(handleSize.width(), hScrollBar->preferSize(0, 0).width());
			if (vScrollPolicy == ScrollPolicy_Auto)
			{
				boss->setPerch(Part_Right, width);
				vScrollBar->setRect(boss->rect(Part_Right));
				vScrollBar->setVisible(crect.height() < area.height());
			}
			if (vScrollPolicy == ScrollPolicy_Always)
			{
				boss->setPerch(Part_Right, width);
				vScrollBar->setRect(boss->rect(Part_Right));
				vScrollBar->setVisible(true);
			}
			if (vScrollPolicy == ScrollPolicy_Floating)
			{
				BRect rrect = boss->rect(Part_Right);
				vScrollBar->setRect(rrect.right() - width, rrect.y(), width, crect.height());
			}
		}
		vScrollBar->setParent(boss);
		vScrollBar->setRange(0, area.height());
		vScrollBar->setPage(crect.height());
		vScrollBar->setValue(crect.top() - area.top());
		vScrollBar->raise();
	}
}

void member_BScrollArea::slotMouseLeaveVerticalScrollBar()
{
	vScrollBar->hide();
}
void member_BScrollArea::slotVerticalScrollStepChanged(BObject* object, const BValue& value)
{

}
void member_BScrollArea::slotVerticalScrollValueChanged(BObject* object, const BValue& value)
{
	BRect crect = boss->centerRect();
	int xoffset = hScrollBar->value();
	int yoffset = vScrollBar->value();
	int x = crect.x() - xoffset;
	int y = crect.y() - yoffset;
	if (rawArea.pos() != BPoint(x, y))
	{
		rawArea.setPos(x, y);
		applyAreaPolicy();
		boss->scrollArea();
		boss->fresh();
	}
}

void member_BScrollArea::slotMouseLeaveHorizontalScrollBar()
{
	hScrollBar->hide();
}
void member_BScrollArea::slotHorizontalScrollStepChanged(BObject* object, const BValue& value)
{
	hstep = value;
}
void member_BScrollArea::slotHorizontalScrollValueChanged(BObject* object, const BValue& value)
{
	BRect crect = boss->centerRect();
	int xoffset = hScrollBar->value();
	int yoffset = vScrollBar->value();
	int x = crect.x() - xoffset;
	int y = crect.y() - yoffset;
	if (rawArea.pos() != BPoint(x, y))
	{
		rawArea.setPos(x, y);
		applyAreaPolicy();
		boss->scrollArea();
		boss->fresh();
	}
}

